package pers.cmc.mysql.core;

import pers.cmc.mysql.model.Config;
import pers.cmc.mysql.model.ConnectionInfo;
import pers.cmc.mysql.model.Select;

import javax.sql.rowset.CachedRowSet;
import javax.sql.rowset.RowSetFactory;
import javax.sql.rowset.RowSetProvider;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 负责mysql池的创建和连接
 * @author EDY
 */
public class Pool {
    Config config;
    List<ConnectionInfo> list = new ArrayList<>();

    static {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /** 创建连接池 */
    public Pool(Config  config) {
        this.config = config;
    }

    public ConnectionInfo connection() throws SQLException {
        String url = "jdbc:mysql://"+config.getMysql().getHost()+":"+config.getMysql().getPort()+"/"+config.getMysql().getDatabase()+"?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";
        Connection connection = DriverManager.getConnection(url,config.getMysql().getUser(),config.getMysql().getPassword());
        ConnectionInfo connectionInfo = new ConnectionInfo(connection,false);
        this.list.add(connectionInfo);
        return connectionInfo;
    }


    /** 获取连接 */
    public ConnectionInfo getConnection() throws SQLException, InterruptedException {
        boolean capacity = true;
        for (int i = 5 ;i > 0;i--){
            // 遍历获取连接
            for (ConnectionInfo c : this.list){
                if(c.getState()){
                    c.setState(false);
                    return c;
                }
            }
            // 连接池的数量如果满了，就等待200毫秒，最多等待5次
            if(config.getMysql().getMaxConnect() == this.list.size()){
                // 等待200毫秒
                Thread.sleep(200);
                continue;
            }
            // 能走到这里说明连接没有满
            capacity = false;
            break;
        }
        if(capacity){
            // 连接池数量翻倍
            config.getMysql().setMaxConnect(config.getMysql().getMaxConnect()*2);
        }

        // 创建一个连接放到连接池
        return connection();
    }

    public List<Map<String,Object>> select(String sql) throws InterruptedException, SQLException {
        return select(sql,new ArrayList<>());
    }

    public List<Map<String,Object>> select(Select select) throws InterruptedException, SQLException {
        return select(select.getSql(),select.getParam());
    }

    /** 执行查询 */
    public List<Map<String,Object>> select(String sql, List<Object> args) throws InterruptedException, SQLException {
        //获取一条连接
        ConnectionInfo connection = getConnection();
        //创建查询变量,进行查询
        PreparedStatement pst= connection.getConnection().prepareStatement(sql);

        for(int i=0;i<args.size();i++){
            //1表示的是第一个问号的数据为
            pst.setString((i+1),args.get(i).toString());
        }
        //获取到结果集了
        ResultSet rs = pst.executeQuery();
        //离线查询
        //通过RowSetProvider的静态方法创建RowSetFactory对象
        RowSetFactory rowSetFactory = RowSetProvider.newFactory();
        //创建CachedRowSet对象
        CachedRowSet cachedRowSet = rowSetFactory.createCachedRowSet();
        //使用结果集填充cachedRowSet22
        cachedRowSet.populate(rs);

        //关闭连接
        rs.close();
        pst.close();

        //释放连接回连接池
        connection.close();

        return convertList(cachedRowSet);
    }




    private static List<Map<String,Object>> convertList(ResultSet rs) throws SQLException{
        List<Map<String,Object>> list = new ArrayList<>();
        //获取键名
        ResultSetMetaData md = rs.getMetaData();
        //获取列的数量
        int columnCount = md.getColumnCount();
        while (rs.next()) {
            //声明Map
            Map<String,Object> rowData = new HashMap<>();
            for (int i = 1; i <= columnCount; i++) {
                //获取键名及值
                rowData.put(md.getColumnName(i), rs.getObject(i));
            }
            list.add(rowData);
        }
        return list;
    }

}
